package com.xtiim.battery.discharge.event;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
public class DefaultEventMulticaster implements EventMulticaster {

    private static DefaultEventMulticaster instance = new DefaultEventMulticaster();

    private Map<Class<?>, List<ApplicationListener>> eventListenerMap = Maps.newConcurrentMap();

    private DefaultEventMulticaster() {}

    public static DefaultEventMulticaster getInstance() {
        return instance;
    }

    @Override
    public void register(Class<?> eventClazz, ApplicationListener listener) {
        Type[] genericInterfaces = listener.getClass().getGenericInterfaces();
        if (genericInterfaces != null) {
            ParameterizedType parameterizedType = (ParameterizedType) genericInterfaces[0];
            Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
            if (actualTypeArgument instanceof Class<?> && eventClazz.isAssignableFrom((Class<?>) actualTypeArgument)) {
                synchronized (eventListenerMap) {
                    eventListenerMap.computeIfAbsent(eventClazz, k -> new ArrayList<>()).add(listener);
                }
            }
        }
    }

    @Override
    public List<ApplicationListener> getListeners(Class<?> eventClazz) {
        return eventListenerMap.get(eventClazz);
    }
}
